package net.alvin.gitlab;

import net.alvin.io.ExcelOutputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.ProjectFilter;
import org.gitlab4j.api.models.User;
import reactor.core.publisher.Flux;

import java.io.FileNotFoundException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class GitlabStatistics {

    private static final Logger logger = LogManager.getLogger(GitlabStatistics.class);

    private static final Comparator<Project> byProjectName = Comparator.comparing(Project::getNameWithNamespace);
    private static final Comparator<Project> byProjectPath = Comparator.comparing(Project::getPathWithNamespace);
    private static final Comparator<Project> byStorageSize = Comparator.comparing(project -> project.getStatistics().getStorageSize());

    private final GitLabApi gitLabApi;
    private final String gitlabHost;
    private final ExcelOutputStream excel;

    public GitlabStatistics(String gitlabHost, String token, String outputFile) throws FileNotFoundException {
        this.gitlabHost = gitlabHost;
        this.gitLabApi = new GitLabApi(gitlabHost, token);
        this.excel = new ExcelOutputStream(outputFile);
    }


    public void writeProjectSheet(long storageSize) {
        try {
            ProjectFilter filter = new ProjectFilter();
            filter.withStatistics(true);
            logger.info("[连接到：{}] 开始收集 gitlab-large-projects 数据...", gitlabHost);
            Stream<Project> projectStream = gitLabApi.getProjectApi().getProjectsStream(filter);
            Flux.fromStream(projectStream).filter(project -> project.getStatistics().getStorageSize() > storageSize)
                    .sort(byProjectName)
                    .map(project -> {
                        String owner = project.getOwner() != null ? project.getOwner().getUsername() : "";
                        Map<String, Object> row = new HashMap<>();
                        row.put("项目名称", project.getName());
                        row.put("项目描述", project.getDescription());
                        row.put("所属空间", project.getNamespace().getName());
                        row.put("项目属主", owner);
                        row.put("项目地址", project.getWebUrl());
                        row.put("项目大小", project.getStatistics().getStorageSize() / 1024 / 1024 + "MB");
                        logger.info("输出数据: {}", row);
                        return row;
                    }).collectList()
                    .subscribe(list -> {
                        excel.createSheet("gitlab-large-projects", list);
                        logger.info("gitlab-large-projects 数据写入完成");
                    });
        } catch (GitLabApiException e) {
            logger.error(e.getStackTrace());
        }
    }

    public void writeUserSheet() {
        try {
            logger.info("[连接到：{}] 开始收集 gitlab-users 数据...", gitlabHost);
            Stream<User> activeUsersStream = gitLabApi.getUserApi().getActiveUsersStream();
            Flux.fromStream(activeUsersStream)
                    .map(user -> {
                        Map<String, Object> row = new HashMap<>();
                        row.put("用户名称", user.getName());
                        row.put("邮箱", user.getEmail());
                        row.put("最近活动日期", user.getLastActivityOn());
                        row.put("登录名称", user.getUsername());
                        row.put("管理员", user.getIsAdmin());
                        row.put("状态", user.getState());
                        logger.info("输出数据: {}", row);
                        return row;
                    }).collectList()
                    .subscribe(list -> {
                        excel.createSheet("gitlab-users", list);
                        logger.info("gitlab-users 数据写入完成");
                    });
        } catch (GitLabApiException e) {
            logger.error(e.getStackTrace());
        }
    }

    public void writeAndCloseExcel() {
        excel.write();
        logger.info("Excel 写入 {} 完成", excel.getFilename());
    }
}
